﻿
using System;
using System.Collections.ObjectModel;
using System.Xml.Serialization;

namespace QLab.Controllers.SolutionExplorer
{

	public class SolutionItemList : ObservableCollection<SolutionExplorerItemBase> { }

	[XmlInclude(typeof(SolutionExplorerItemSolution))]
	[XmlInclude(typeof(SolutionExplorerItemProject))]
	[XmlInclude(typeof(SolutionExplorerItemFolder))]
	[XmlInclude(typeof(SolutionExplorerItemFile))]
	public abstract class SolutionExplorerItemBase
	{
		protected SolutionExplorerItemType _itemType;
		protected SolutionItemList _child_items = null;
		protected string _full_path = String.Empty;
		protected string _name = string.Empty;
		protected string _node_text = String.Empty;

		/// <summary>
		/// Default constructor
		/// </summary>
		public SolutionExplorerItemBase(SolutionExplorerItemType ItemType)
		{
			_itemType = ItemType;
			Parent = null;

			if (!ItemType.Equals(SolutionExplorerItemType.Q_File))
				_child_items = new SolutionItemList();
		}

		public void AddNewItem(SolutionExplorerItemType NewItemType)
		{
			SolutionExplorerItemBase solution = GetTopParentNode() as SolutionExplorerItemSolution;
			if (solution == null)
			{
				// error message
				return;
			}

			frmTextInput fTI;
			SolutionExplorerItemBase newItem = null;

			switch (NewItemType)
			{
				case SolutionExplorerItemType.Project:
					fTI = new frmTextInput();
					fTI.ShowDialog("New Project");
					if (fTI.DialogResult.HasValue && fTI.DialogResult.Value)
					{
						string projectName = System.IO.Path.GetFileNameWithoutExtension(fTI.InputText);
						newItem = new SolutionExplorerItemProject(
						  System.IO.Path.GetDirectoryName(solution.FullPath),
						  System.IO.Path.GetFileNameWithoutExtension(fTI.InputText));
					}
					break;

				case SolutionExplorerItemType.Folder:
					fTI = new frmTextInput();
					fTI.ShowDialog("New Folder");
					if (fTI.DialogResult.HasValue && fTI.DialogResult.Value)
						newItem = new SolutionExplorerItemFolder() { Name = fTI.InputText };
					break;

				case SolutionExplorerItemType.Q_File:
					fTI = new frmTextInput();
					fTI.ShowDialog("New File");
					if (fTI.DialogResult.HasValue && fTI.DialogResult.Value)
						newItem = new SolutionExplorerItemFile()
						{
							Name = System.IO.Path.GetFileNameWithoutExtension(fTI.InputText) + GetDefaultFileExtension(NewItemType)
						};
					break;
			}

			if (newItem != null)
			{
				newItem.Parent = this;
				newItem.Save();
				ChildItems.Add(newItem);

				solution.Save();
			}
		}

		#region Abstract

		public abstract void Load(string Path);
		public abstract void Save();

		#endregion abstract

		protected void UpdateParentNodes()
		{
			foreach (SolutionExplorerItemBase item in ChildItems)
			{
				item.Parent = this;
				item.UpdateParentNodes();
			}
		}

		protected SolutionExplorerItemBase GetTopParentNode()
		{
			SolutionExplorerItemBase item = this;
			while (true)
			{
				if (item.Parent == null)
					return item;
				item = item.Parent;
			}
		}

		protected string GetFullPath()
		{
			if (!String.IsNullOrEmpty(_full_path))
				return _full_path;

			string path = String.Empty;

			if (Type.Equals(SolutionExplorerItemType.Solution))
			{
				path = ((SolutionExplorerItemSolution)this).SolutionRootPath;
			}
			else
			{
				SolutionExplorerItemBase item = this;

				// Projects have folders
				if (Type.Equals(SolutionExplorerItemType.Project))
				{
					path = ((SolutionExplorerItemProject)this).ProjectRootPath;
					if (path == null)
						path = "";
				}
				while ((item = item.Parent) != null)
					switch (item.Type)
					{
						case SolutionExplorerItemType.Solution:
							path = System.IO.Path.Combine(((SolutionExplorerItemSolution)item).SolutionRootPath, path);
							break;

						case SolutionExplorerItemType.Project:
							path = System.IO.Path.Combine(item.NodeText, path);
							break;

						case SolutionExplorerItemType.Folder:
							path = System.IO.Path.Combine(item.NodeText, path);
							break;

						case SolutionExplorerItemType.Q_File:
							// Error. File can not be a parent node.
							return "";
					}
			}
			_full_path = System.IO.Path.Combine(path, _name);
			return _full_path;
		}

		#region Properties

		[XmlIgnoreAttribute()]
		public SolutionExplorerItemType Type
		{
			get { return _itemType; }
		}

		[XmlIgnoreAttribute()]
		public string NodeText
		{
			get { return _node_text; }
		}

		[XmlAttribute("Name")]
		public string Name
		{
			get { return _name; }
			set
			{
				_name = value;
				if (Type.Equals(SolutionExplorerItemType.Folder))
					_node_text = _name;
				else
					_node_text = System.IO.Path.GetFileNameWithoutExtension(_name);
			}
		}

		[XmlIgnoreAttribute()]
		public string FullPath
		{
			get { return GetFullPath(); }

			/*
			set
			{

			  _full_path = value;

			  switch (_itemType)
			  {
				case SolutionExplorerItemType.Solution:
				  _node_text = System.IO.Path.GetFileNameWithoutExtension(_path);
				  break;

				case SolutionExplorerItemType.Project:
				  _node_text = System.IO.Path.GetFileNameWithoutExtension(_path);
				  break;

				case SolutionExplorerItemType.Folder:
				  System.IO.DirectoryInfo dir = new System.IO.DirectoryInfo(_path);
				  _node_text = dir.Name;

				  //LoadFolderItems();
				  break;

				case SolutionExplorerItemType.Q_File:
				  _node_text = System.IO.Path.GetFileName(_path);
				  break;
			  }
			}
			 */

		}

		[XmlIgnoreAttribute()]
		public string ImageSource
		{
			get { return SolutionExplorerItemImage.ImageSourcePath(_itemType); }
		}

		/// <summary>
		/// Gets the list of child items
		/// This needs to be an observable collection so we can modify the content and keep the UI updated
		/// </summary>
		[XmlElement("BaseItem", typeof(SolutionExplorerItemBase)), XmlElement("Project", typeof(SolutionExplorerItemProject)),
		 XmlElement("Folder", typeof(SolutionExplorerItemFolder)), XmlElement("File", typeof(SolutionExplorerItemFile))]
		public SolutionItemList ChildItems
		{
			get { return _child_items; }
			set { _child_items = value; }
		}

		[XmlIgnoreAttribute()]
		public SolutionExplorerItemBase Parent { get; set; }


		[XmlIgnoreAttribute()]
		public string DefaultFileExtension { get { return GetDefaultFileExtension(Type); } }

		#endregion

		public static string GetDefaultFileExtension(SolutionExplorerItemType sType)
		{
			switch (sType)
			{
				case SolutionExplorerItemType.Solution:
					return ".qlsln";
				case SolutionExplorerItemType.Project:
					return ".qlproj";
				case SolutionExplorerItemType.Q_File:
					return ".q";
				default:
					return "";
			}
		}
	}
}
